#import matplotlib.pyplot as plt

import backend
import data


def attack(attacker, target, genre='melee', move_type='normal', stealth=0, accuracy=0, force=0, lethality=1, daze=0, stun=0, cost=10):
    result = ''
    attacker.WAIT += cost
    piercing = backend.roll(attacker.skills['stealth']+stealth, t=target.skills['detection'])
    if piercing > data.PIERCING_REQ or target.stats['stamina'] <= 0:
        result = target.alter_stats({'strength': max(0, (
            lethality-target.resistance))*-1, 'focus': max(0, (daze-target.clarity))*-1})
        if not result:
            result = 'crit'
    else:
        hit = backend.roll(attacker.skills['accuracy']+accuracy, t=target.skills['evasion'])
        if hit < 0:
            result = 'miss'
        else:
            dmg = backend.roll(attacker.skills['force']+force, t=target.skills['guard'])
            if dmg > 0:
                target.alter_stats({'stamina': max(0, dmg)*-1})
                result = 'hit'
            else:
                result = 'blocked'
    return result

def d(a, b):
    if b != 0:
        return float(a)/b
    else:
        return 0

def fight2death(unit1, unit2, move_type1='normal', move_type2='normal'):
    winner = None
    attacked_1 = 0
    attacked_2 = 0
    crit_1 = 0
    crit_2 = 0
    miss_1 = 0
    miss_2 = 0
    hit_1 = 0
    hit_2 = 0
    blocked_1 = 0
    blocked_2 = 0
    while winner is None:
        if unit1.WAIT < 1 and unit1.stats['stamina']:
            attacked_1 += 1
            result = attack(unit1, unit2, move_type=move_type1,
                   stealth=unit1.bonus_stealth[move_type1], daze=unit1.daze[move_type1],
                   accuracy=unit1.bonus_accuracy[move_type1], force=unit1.bonus_force[move_type1],
                   lethality=unit1.lethality[move_type1], cost=unit1.attack_time[move_type1])
            if result == 'die':
                winner = True
                crit_1 += 1
            elif result == 'crit':
                crit_1 += 1
            elif result == 'miss':
                miss_1 += 1
            elif result == 'hit':
                hit_1 += 1
            else: blocked_1 += 1
        if unit2.WAIT < 1 and unit2.stats['stamina']:
            attacked_2 += 1
            result = attack(unit2, unit1, move_type=move_type2,
                      stealth=unit1.bonus_stealth[move_type2], daze=unit1.daze[move_type2],
                      accuracy=unit1.bonus_accuracy[move_type2], force=unit1.bonus_force[move_type2],
                      lethality=unit1.lethality[move_type2], cost=unit1.attack_time[move_type2])
            if result == 'die':
                winner = False
                crit_2 += 1
            elif result == 'crit':
                crit_2 += 1
            elif result == 'miss':
                miss_2 += 1
            elif result == 'hit':
                hit_2 += 1
            else: blocked_2 += 1
        unit1.regen()
        unit2.regen()
        unit1.WAIT -= 1
        unit2.WAIT -= 1
    return [winner, attacked_1, attacked_2, 
            d(crit_1,attacked_1), d(crit_2,attacked_2), 
            d(miss_1,attacked_1), d(miss_2,attacked_2), 
            d(hit_1,attacked_1), d(hit_2,attacked_2), 
            d(blocked_1,attacked_1), d(blocked_2,attacked_2)
    ]

def tournament(fights=100, stats1=None, stats2=None, move_type1='normal', move_type2='normal'):
    if not stats1: stats1 = {'strength': 1, 'stamina': 1, 'focus': 1}
    if not stats2: stats2 = {'strength': 1, 'stamina': 1, 'focus': 1}
    results = []
    for _ in xrange(fights):
        results.append(fight2death(backend.Unit(stats=stats1, WAIT=5), backend.Unit(stats=stats2, WAIT=6), move_type1, move_type2))
    return [list(i) for i in zip(*results)]

def tournament_stats(stats):
    return ['{:.2f}'.format(float(sum(stats[i]))/len(stats[i])) for i in range(len(stats))]

def median(x):
    x = sorted(x)
    return x[len(x)/2]

def percentiles(x, confidence=5):
    x = sorted(x)
    lower = confidence/100.0
    upper = 1 - lower
    return x[int(lower*len(x))], median(x), x[int(upper*len(x))]
        
if __name__ == '__main__':
    import itertools, time
    #fig = plt.figure()
    #ax = fig.add_subplot(111)
    move_dict = {'n':'normal', 'r':'run'}
    x = range(1, 3)
    move_types = ['n', 'r']
    stat_combos = list(itertools.product(x,x,x,x,x,x,move_types,move_types))
    #stat_combos = [1,1,1,1,1,1,'normal','normal']
    results = []
    #stuff = [[], [], []]
    t = time.time()
    print 'SrSaFcMv vs SrSaFcMv: win_pct numatt1 numatt2 crits_1 crits_2 misses1 misses2 hits__1 hits__2 blockd1 blockd2'
    for combo in stat_combos:
        stats = tournament_stats(tournament(50, {'strength': combo[0], 'stamina': combo[1], 'focus': combo[2]}, {'strength': combo[3], 'stamina': combo[4], 'focus': combo[5]}, move_dict[combo[6]], move_dict[combo[7]]))
        #results.append(('{0}-{1}-{2}: {6} vs {3}-{4}-{5}: {7}'.format(*combo), stats))
        print '{0}-{1}-{2}: {6} vs {3}-{4}-{5}: {7}'.format(*combo), stats
    print 'done {} tournaments in {} seconds'.format(len(stat_combos), time.time() - t)
    #print '\n'.join([str(v) for v in sorted(results, key=lambda x: x[1][1][2])[-25:]])
    #ax.plot(stuff[0])
    #ax.plot(stuff[1])
    #ax.plot(stuff[2])
    #ax.set_xlabel('strength')
    #ax.set_ylabel('rounds of fighting')
    #ax.legend(('10th percentile', 'Median', '90th Percentile'))
    #plt.show()
